package com.wl.designpattern.visitor;

/**
 * 访问者模式
 * 封装某些作用于某种数据结构中各元素的操作，它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
 *
 * Visitor（抽象访问者）：接口或者抽象类，为每一个元素（Element）声明一个访问的方法。
 * ConcreteVisitor（具体访问者）：实现抽象访问者中的方法，即对每一个元素都有其具体的访问行为。
 * Element（抽象元素）：接口或者抽象类，定义一个accept方法，能够接受访问者（Visitor）的访问。
 * ConcreteElementA、ConcreteElementB（具体元素）：实现抽象元素中的accept方法，通常是调用访问者提供的访问该元素的方法。
 * Client（客户端类）：即要使用访问者模式的地方。
 *
 * 应用场景
 * 对象结构比较稳定，很少改变，但是经常需要在此对象结构上定义新的操作行为时。
 * 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
 *
 * 优点
 * 各种角色各司其职，符合单一职责原则。
 * 原有的类上新增操作只需实现一个具体访问者就可以，不 必修改整个类层次，符合开闭原则。
 * 良好的扩展性，新增访问操作变得简单。
 * 数据操作和数据结构的解耦。
 *
 * 缺点
 * 具体元素对访问者公布了实现细节，破坏了类的封装性，违反了迪米特原则。
 * 违反了依赖倒置原则，为了达到区别对待依赖了具体而不是抽象。
 * 具体元素修改的成本太大。
 * 新增具体元素困难，需要在抽象访问者角色中增加一个新的抽象操作，违反了开闭原则。
 *
 * android 应用 此模式应用较少
 *
 * Created by wangliang on 2021/2/27.
 */
public class Test {
    public static void main(String[] args) {
        //创建不同的元素
        Music wangyiyue = new Music("网易云音乐");
        Music kugou = new Music("酷狗");
        Video youku = new Video("优酷");
        Video iqiyi = new Video("爱奇艺");

        //放入对象结构中
        Websites websites = new Websites();
        websites.addWeb(wangyiyue);
        websites.addWeb(kugou);
        websites.addWeb(youku);
        websites.addWeb(iqiyi);

        Visitor idler1 = new Idler("闲人1号");
        websites.accept(idler1);//集合接受idler1的访问

        System.out.println("-------------------------------------");
        Visitor busy1 = new Busy("忙人2号");
        websites.accept(busy1);////集合接受busy1的访问
    }
}
